﻿<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=10,11,edge" />
  <title></title>
  <!-- <script type="text/javascript" src="./dist/LercDecode.min.js"></script> -->
  <!-- <script type="text/javascript" src="https://unpkg.com/lerc@latest/LercDecode.min.js"></script> -->
  <script type="text/javascript" src="./dist/LercDecode.js"></script>
</head>

<body>
  <div id="imageInfo">Image Header Info</div>
  <div id="currentPV">Hover over to see current pixel value</div>
  <input id="lercBlobUrl" type="text" style="width:90%" value="" onchange="showTile()">
  <div id="divControls" style="display:none;">
    <button onclick="showTile(-1)">Previous</button>&nbsp;
    <button onclick="showTile(1)">Next</button>&nbsp;
    <button onclick="autoShow(this)">Auto</button>&nbsp;
    <span id="currentIndex"></span>
  </div>
  <div>
    <canvas width="100" height="100" id="imageCanvas"></canvas>
  </div>
  <!-- <script type="module">
    import * as Lerc from "./dist/LercDecode.es.js"; -->
  <script type="text/javascript">
    let showTile;
    const defaultUrl =
      "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer/tile/0/0/0";
    function main() {
      const { load, isLoaded, decode } = Lerc;
      showTile = (next) => (load().then(() => showTile1(next)));
      const sanity = () => load().then(() => {
        const ndim = "76,101,114,99,50,32,5,0,0,0,45,25,25,193,20,0,0,0,30,0,0,0,3,0,0,0,88,2,0,0,8,0,0,0,85,7,0,0,1,0,0,0,0,0,0,0,0,0,224,63,0,0,0,0,0,0,0,0,0,0,0,0,0,64,86,64,0,0,0,0,0,30,60,29,59,89,1,13,57,68,14,59,80,20,36,84,16,33,65,5,45,87,17,51,76,27,52,83,26,46,83,20,30,69,2,54,63,27,30,79,2,39,76,25,33,77,4,35,61,14,49,79,4,41,77,17,46,73,12,32,87,1,53,83,29,59,88,14,43,84,24,40,64,6,46,80,18,38,69,12,49,82,22,34,65,17,42,77,15,38,82,2,56,78,22,51,66,4,47,88,23,45,80,6,34,83,7,35,83,29,56,86,18,39,82,25,30,79,19,58,70,18,47,73,7,49,82,6,46,81,8,49,81,7,44,83,18,30,86,1,58,84,18,31,81,11,39,81,13,35,73,3,51,85,28,53,88,22,40,86,26,35,86,26,47,88,11,58,81,0,45,86,3,53,73,24,38,87,16,40,68,10,41,82,5,50,66,21,40,71,5,58,84,24,42,67,3,48,89,12,39,79,9,56,75,1,40,61,14,53,65,28,59,69,4,46,85,12,58,60,5,57,84,5,41,87,23,47,75,8,57,76,22,46,86,4,52,84,1,33,86,29,37,84,6,42,78,10,55,64,29,52,61,13,42,76,15,48,68,18,57,76,18,36,60,21,43,61,14,38,78,25,36,72,7,55,63,3,50,82,29,55,64,12,38,89,17,51,72,29,39,73,27,44,65,22,55,70,18,47,87,26,58,61,20,43,61,2,37,68,6,49,89,0,33,61,26,41,80,10,57,89,19,59,62,23,47,83,11,44,71,19,41,89,26,30,81,2,40,83,24,50,81,16,31,60,27,31,77,21,47,72,2,32,89,15,54,71,6,46,82,5,46,80,6,49,63,7,46,67,8,36,61,2,39,67,18,54,66,29,59,88,29,44,86,0,56,63,3,52,67,26,37,69,6,36,64,14,30,66,25,59,70,21,41,70,13,53,80,19,34,86,1,44,60,5,39,76,23,47,75,19,48,73,10,59,65,13,50,85,23,49,75,18,36,70,2,30,76,11,32,77,2,30,64,25,47,83,22,32,67,15,34,80,16,39,66,13,59,64,18,46,66,15,30,66,3,51,82,8,48,89,0,58,65,20,36,60,3,42,67,12,53,67,14,48,89,12,54,77,1,43,86,21,43,73,12,43,88,4,40,67,8,31,73,1,55,60,16,40,76,2,48,89,13,57,75,13,40,86,26,36,79,22,49,88,27,56,77,20,30,69,7,45,60,8,35,85,28,41,78,5,30,75,17,51,88,18,48,75,12,35,76,25,42,65,2,36,74,27,37,80,14,32,79,28,55,83,3,39,81,8,34,65,8,59,76,25,35,85,11,47,79,13,42,86,13,41,64,6,30,78,4,51,63,2,47,73,29,51,71,11,30,83,16,37,82,6,41,73,25,43,69,11,44,66,0,41,63,26,48,61,1,47,86,1,34,78,9,46,71,26,38,83,10,49,87,19,49,84,20,45,63,2,44,66,5,42,63,2,31,77,28,40,72,11,34,60,11,45,61,4,32,87,4,35,61,16,37,77,20,53,80,20,58,63,7,50,75,16,55,63,19,57,82,4,51,75,18,59,89,15,43,87,2,39,64,25,59,77,23,35,62,28,39,70,15,32,68,11,52,81,4,44,82,15,49,74,1,37,63,26,39,80,25,31,70,4,36,89,27,31,60,20,54,82,23,43,61,17,34,74,3,34,82,1,46,89,3,53,84,2,38,79,24,43,69,15,42,71,28,43,74,6,44,61,19,36,70,12,45,88,17,43,79,9,53,68,13,49,79,14,39,73,16,45,85,25,31,79,17,38,64,0,46,87,8,34,68,20,56,69,27,40,76,22,41,66,25,49,70,27,50,79,29,30,78,7,33,67,16,58,79,24,54,71,11,39,89,7,38,88,1,56,72,17,51,80,18,54,80,6,50,73,9,30,87,22,42,81,23,47,78,4,55,86,4,42,88,6,44,60,11,39,85,14,47,61,29,31,86,22,40,88,10,49,69,20,46,74,0,51,68,7,48,75,8,34,60,19,39,67,20,46,70,22,54,66,17,31,76,29,44,81,5,46,85,5,52,74,21,32,66,20,53,87,25,32,89,0,31,81,3,41,89,10,44,89,19,54,75,12,52,77,6,53,64,18,47,61,23,35,71,13,37,76,8,31,82,7,53,63,29,46,67,6,34,86,8,59,74,12,38,62,21,55,65,3,43,86,6,43,84,17,58,84,7,45,80,3,50,85,29,30,84,10,40,81,27,36,69,27,41,83,23,56,63,4,51,74,6,51,61,2,34,74,17,45,64,3,52,77,25,42,80,2,50,76,9,41,74,10,48,65,26,51,88,29,45,64,25,52,75,15,52,69,3,34,80,24,58,71,3,59,74,8,44,76,29,38,78,26,51,88,8,58,89,0,56,71,4,45,74,11,56,88,24,47,80,27,53,66,29,34,86,9,54,62,28,50,67,0,54,80,6,55,63,1,32,84,23,42,84,12,58,66,23,44,88,12,54,71,13,58,71,24,43,62,25,38,81,0,38,65,19,58,89,8,42,76,9,58,85,3,48,65,2,50,64,2,58,66,1,42,75,13,49,69,25,51,88,16,48,83,6,41,76,1,52,65,15,54,75,28,51,75,28,45,60,15,40,77,28,30,74,5,33,63,29,47,82,5,43,72,16,42,76,1,59,78,19,48,62,10,48,74,4,31,70,26,41,65,19,31,71,11,41,87,13,34,84,25,31,84,10,33,78,17,52,73,9,43,63,8,40,64,3,38,76,6,54,60,9,30,84,18,55,75,6,34,84,20,39,72,12,54,87,8,51,81,5,39,63,18,48,87,8,45,72,22,55,86,16,50,65,22,31,72,7,37,64,4,42,67,20,49,72,22,38,75,22,35,84,6,52,67,27,45,72,17,34,65,10,53,88,22,34,88,23,34,82,6,51,82,14,45,61,17,54,75,18,52,71,10,47,74,15,44,75,9,34,79,15,42,81,0,33,76,3,37,69,9,36,72,15,48,61,0,44,65,27,47,79,19,51,74,2,44,70,27,44,67,11,46,70,28,43,66,23,37,67,19,35,73,13,44,82,10,32,74,7,48,82,25,50,73,6,37,80,20,38,74,14,54,89,14,51,73,23,36,73,1,52,68,2,48,67,3,56,73,26,37,85,3,35,82,20,57,84,10,38,82,14,33,74,24,55,76,17,35,66,24,32,72,29,34,82,4,40,63,8,49,88,22,47,65,13,55,89,5,42,86,22,35,83,22,35,69,26,40,88,27,37,84,14,33,64,14,59,81,5,57,60,6,47,82,21,42,64,22,37,67,29,30,63,9,34,76,17,34,67,29,43,83,19,46,75,22,44,60,28,36,89,0,39,81,25,42,80,4,34,83,20,33,81,14,31,80,26,56,67,15,33,82,26,55,73,4,42,62,5,58,75,26,36,60,21,46,89,26,38,82,14,45,78,10,53,66,16,41,66,11,45,62,19,49,61,8,42,80,10,33,72,7,46,89,1,49,77,8,40,63,27,50,61,13,34,84,19,35,64,4,59,69,11,54,76,7,42,68,18,31,83,27,58,68,23,47,74,0,45,81,21,49,75,18,56,78,19,55,70,22,51,77,28,38,83,15,37,89,5,54,76,14,46,83,29,35,74,21,31,74,25,51,65,4,40,77,12,50,67,4,54,76,21,51,81,9,41,81,22,39,81,6,30,76,19,35,82,2,46,85,20,56,84,11,31,88,9,41,75,20,57,73,16,42,65,2,59,73,7,37,72,6,59,74,12,51,70,4,59,62,9,39,64,1,54,73,28,46,74,2,51,73,3,35,83,20,33,65,13,41,82,8,45,77,19,59,66,7,47,76,13,37,70,10,35,73,0,47,65,14,48,61,16,59,67,0,39,86,22,58,84,9,30,82,1,38,68,11,30,77,28,37,72,9,57,66,10,42,82,2,41,68,16,43,67,2,57,86,16,47,61,21,53,82,0,47,65,5,56,70,5,50,83,26,33,78,21,34,79,27,39,65,12,57,70,14,40,81,20,52,71,0,52,87,9,31,79,17,36,65,13,47,69,13,40,73,25,33,78,16,33,73,11,46,71".split(",")
          .map((x) => Number(x));
        const result = decode(ndim);
        console.log(result);
        let pass = result.width === 30 && result.height === 20 && result.bandCount === 1 && result.pixelType === "U8" && result.dimCount === 3 && result.mask == null;
        const bandStat = result.statistics[0];
        pass = pass && bandStat.minValue === 0 && bandStat.maxValue === 89 && bandStat.dimStats.minValues.join(",") === "0,30,60";
        const min0 = Math.min.apply(null, result.pixels[0].slice(0, 600))
        const min1 = Math.min.apply(null, result.pixels[0].slice(600, 1200))
        const min2 = Math.min.apply(null, result.pixels[0].slice(1200))
        pass = min0 === 0 && min1 === 30 && min2 === 60;
        if (pass) {
          const bipResult = decode(ndim, { returnPixelInterleavedDims: true });
          pass = bipResult.pixels[0].slice(0, 6).join(",") === "13,57,68,14,59,80";
        }
        if (pass) {
          console.log("ndim sanity passed");
        } else {
          console.error("ndim sanity failed");
          alert("ndim sanity failed");
        }
      });
      sanity();

      const url =
        location.search.indexOf("?url=") === 0
          ? location.search.slice(5)
          : defaultUrl;
      const autoShowInterval = 3000;
      let showNext, list;
      if (url.indexOf(".txt") > 0) {
        const listXhr = new XMLHttpRequest();
        listXhr.open("Get", url, true);
        listXhr.responseType = "text";
        listXhr.send();
        listXhr.onload = () => {
          list = listXhr.response.split("\r\n");
          currentIndex = -1;
          document.getElementById("divControls").style.display = "block";
          showTile(1);
        };
        listXhr.onerror = () => {
          url = defaultUrl;
          document.getElementById("lercBlobUrl").value = url;
          showTile();
        };
      } else {
        document.getElementById("lercBlobUrl").value = url;
        showTile();
      }
      function autoShow(btn) {
        if (showNext) {
          clearTimeout(showNext);
          showNext = null;
          btn.innerText = "Auto";
        } else {
          btn.innerText = "Pause";
          autoShowNext();
        }
      }

      function autoShowNext() {
        showNext = setTimeout(() => {
          showTile(1);
          if (currentIndex < list.length - 1 && showNext) {
            autoShowNext();
          }
        }, autoShowInterval);
      }

      function showTile1(next) {
        if (!isLoaded) {
          return;
        }
        if (next === -1) {
          if (currentIndex > 0) {
            document.getElementById("lercBlobUrl").value = list[--currentIndex];
          }
        } else if (next === 1) {
          if (currentIndex < list.length - 1) {
            document.getElementById("lercBlobUrl").value = list[++currentIndex];
          }
        }
        if (list) {
          document.getElementById("currentIndex").innerText =
            currentIndex + 1 + "/" + list.length;
        }
        //UI elements
        const div_Info = document.getElementById("imageInfo");
        const div_CurrentPv = document.getElementById("currentPV");
        const imageCanvas = document.getElementById("imageCanvas");
        const canvasPos = imageCanvas.getBoundingClientRect();
        const context = imageCanvas.getContext("2d");
        const lercBlobUrl = document.getElementById("lercBlobUrl").value || defaultUrl;
        //div_Header.innerHTML = "test";
        //if it fails you'll see the red
        context.clearRect(0, 0, imageCanvas.width, imageCanvas.height);
        context.fillStyle = "red";
        context.fillRect(0, 0, 100, 100);
        //fetching lerc blob
        const xhr = new XMLHttpRequest();
        xhr.open("Get", lercBlobUrl, true);
        xhr.responseType = "arraybuffer";
        xhr.send();
        let pixels, width, mask;
        xhr.onreadystatechange = () => {
          if (xhr.readyState == 4 && xhr.status == 200) {
            const t0 = performance.now();
            const result = decode(xhr.response);
            ({ pixels, width, mask } = result);
            const { height, statistics, dimCount } = result;
            const duration = performance.now() - t0;
            imageCanvas.width = width;
            imageCanvas.height = height;

            const imageData = context.createImageData(width, height);
            const data = imageData.data;
            const nPixels = width * height;
            const planes = pixels.length;

            const min = Math.min.apply(null, statistics.map((x) => x.minValue));
            const max = Math.max.apply(null, statistics.map((x) => x.maxValue));
            // for demonstration purpose: use same scaling factor for all bands
            const factor = 255 / (max - min);
            if (planes < 3) {
              for (let i = 0; i < nPixels; i++) {
                if (!mask || mask[i]) {
                  const pv = (pixels[0][i] - min) * factor;
                  data[i * 4] = pv;
                  data[i * 4 + 1] = pv;
                  data[i * 4 + 2] = pv;
                  data[i * 4 + 3] = 255;
                } else {
                  data[i * 4 + 3] = 0;
                }
              }
            } else {
              //show first 3 bands here
              for (let i = 0; i < nPixels; i++) {
                if (!mask || mask[i]) {
                  data[i * 4] = (pixels[0][i] - min) * factor;
                  data[i * 4 + 1] = (pixels[1][i] - min) * factor;
                  data[i * 4 + 2] = (pixels[2][i] - min) * factor;
                  data[i * 4 + 3] = 255;
                } else {
                  data[i * 4 + 3] = 0;
                }
              }
            }
            context.putImageData(imageData, 0, 0);
            div_Info.innerHTML =
              "max: " +
              max +
              ", min: " +
              min +
              ", width: " +
              width +
              ", height: " +
              height +
              ", planes: " +
              planes +
              ", dims: " +
              dimCount +
              ", decode time:" +
              duration;
          }
          imageCanvas.onmousemove = (evt) => {
            if (!pixels) {
              return;
            }
            const col = evt.clientX - canvasPos.left; //col
            const row = evt.clientY - canvasPos.top; //row
            var pos = row * width + col;
            if ((mask && mask[pos]) || !mask) {
              const pv = [];
              for (let kk = 0; kk < pixels.length; kk++) {
                pv.push(pixels[kk][pos]);
              }
              div_CurrentPv.innerHTML = "current pixel value: " + pv.join(", ");
            } else {
              div_CurrentPv.innerHTML = "current pixel value: no data";
            }
          };
        };
      }
    }
    main();
  </script>
  <!--load es module and debug TS directly: 
    1. in Lerc.ts (or Lerc.js), change import modules to include .js extension, e.g. ... from "lerc-wasm" to from "lerc-wasm.js"
    2. copy .wasm from dist to wasm folder
    3. no need to comment out bundled LercDecode.js tag at the begging of this page, because es6 module overwrites window.Lerc.
  -->
  <!-- <script type="module"> import("./wasm/Lerc.js").then((Lerc) => { window.Lerc = Lerc; main(); });</script> -->
</body>

</html>